import 'dart:collection';
import 'dart:convert';
import 'package:dio/dio.dart';
import 'dart:developer' as developer;
import 'dart:convert' as convert;
import 'package:flutter/foundation.dart';
import 'result_extension.dart';

/// 默认的日志记录函数，用于调试模式下打印日志信息。
/// [value] 是要记录的日志内容。
void debugLogger(String value) {
  // 如果处于调试模式，使用 developer.log 记录日志信息。
  if (kDebugMode) developer.log(value, name: "CoderXSLee：http_manager");
}

/// 处理服务器返回的数据的类，负责解析和管理响应数据。
class ResponseAnalyzed {
  /// 响应的状态码
  late final String? code;

  /// 响应的消息，用于描述请求的结果或错误信息。
  late String? message;

  /// 响应的主要数据，通常是服务器返回的内容。
  late final dynamic data;

  /// 标识是否将此响应直接展示给用户。
  late bool isExposedToUser;

  /// 原始请求的信息，包含请求的参数、头信息等。
  final RequestOptions? request;

  /// 用于保存解析 JSON 数据的键名：状态码、消息和数据。
  static late String _codeKey, _messageKey, _dataKey;

  /// 构造函数，初始化 [code]、[data]、[message] 和 [isExposedToUser]。
  ResponseAnalyzed({
    this.code,
    this.data,
    this.message,
    this.isExposedToUser = false,
    this.request,
  });

  /// 可选的回调函数，用于在解析结果后进行进一步处理。
  static Function(dynamic)? _resultCheckCallback;

  /// 设置检查解析结果的回调函数。
  /// [callBack] 是回调函数，用于处理解析结果。
  static void setResultCheck(Function(dynamic)? callBack) {
    _resultCheckCallback = callBack;
  }

  /// 设置解析服务器返回的 JSON 字典时使用的键名。
  /// [codeKey] 是状态码的键名。
  /// [messageKey] 是消息的键名。
  /// [dataKey] 是数据的键名。
  /// 假设服务器返回的根数据为：{"code":200, "message": "请求成功", "data": [{},{}]}
  /// 那么应该设置为 ResponseAnalyzed.setResponseKey("code", "message", "data");
  /// 假设服务器返回的根数据为：{"code":200, "msg": "请求成功", "result": [{},{}]}
  /// 那么应该设置为 ResponseAnalyzed.setResponseKey("code", "msg", "result");
  static setResponseKey(String codeKey, String messageKey, String dataKey) {
    _codeKey = codeKey;
    _messageKey = messageKey;
    _dataKey = dataKey;
  }

  /// 解析服务器返回的数据，并检查解析结果。
  /// [response] 是服务器返回的响应数据，可能是 [Response] 或 [HashMap]。
  /// 返回解析后的 [ResponseAnalyzed] 对象。
  static Future<ResponseAnalyzed> analyzingAndCheckup(dynamic response) async {
    if (response is Response) {
      // 如果响应类型是 Dio 的 Response，则调用 _analyzing 方法解析。
      final result = _analyzing(response);
      // 检查解析结果，并返回处理后的 ResponseAnalyzed 对象。
      return _resultCheck(result);
    } else if (response is HashMap<String, dynamic>) {
      // 如果响应类型是 HashMap，直接使用键值对进行解析。
      String? code = response['code'];
      String? msg = response['message'];
      ResponseAnalyzed result = ResponseAnalyzed(code: code, message: msg);
      return _resultCheck(result);
    } else {
      // 对于其他类型的响应，直接返回 ResponseAnalyzed 对象，code 和 message 都为响应内容。
      return ResponseAnalyzed(code: "$response", message: "$response");
    }
  }

  /// 私有方法，用于解析 Dio 的 [Response] 对象，将其转换为 [ResponseAnalyzed] 对象。
  /// [response] 是服务器返回的 Response 对象。
  /// 返回解析后的 [ResponseAnalyzed] 对象。
  static ResponseAnalyzed _analyzing(Response response) {
    // 将服务器返回的 Response 转换为 JSON 对象。
    Map<dynamic, dynamic> json = convert.jsonDecode(response.toString());
    // 如果未设置解析键名，记录日志并返回默认的 ResponseAnalyzed 对象。
    if (_codeKey.isNullOrEmpty || _messageKey.isNullOrEmpty || _dataKey.isNullOrEmpty) {
      debugLogger("解析失败");
      debugLogger("请在 ResponseAnalyzed.setResponseKey() 设置解析键值的key");
      return ResponseAnalyzed(
        code: response.statusCode.toString(),
        message: response.statusMessage,
        data: json,
      );
    }
    // 如果 JSON 数据包含设置的键名，解析数据并返回 ResponseAnalyzed 对象。
    if (json.containsKey(_codeKey) && json.containsKey(_messageKey) && json.containsKey(_dataKey)) {
      return ResponseAnalyzed(
        code: json[_codeKey].toString(),
        message: json[_messageKey].toString(),
        data: json[_dataKey],
        request: response.requestOptions,
      );
    } else {
      // 如果 JSON 数据不包含设置的键名，记录日志并返回默认的 ResponseAnalyzed 对象。
      debugLogger("解析失败");
      debugLogger("服务器返回的json数据格式与 ResponseAnalyzed.setResponseKey(...) 设置的不一致");
      debugLogger("请检查 ResponseAnalyzed.setResponseKey() 设置的 key 是否正确!");
      debugLogger("ResponseAnalyzed.setResponseKey(\"$_codeKey\", \"$_messageKey\", \"$_dataKey\") 设置的 key 是");
      debugLogger("服务器返回的json数据为：${const JsonEncoder.withIndent('  ').convert(json)}");
      return ResponseAnalyzed(
        code: response.statusCode.toString(),
        message: response.statusMessage,
        data: json,
      );
    }
  }

  /// 私有方法，用于检查解析结果，并执行回调函数（如果设置了回调）。
  /// [result] 是解析后的 [ResponseAnalyzed] 对象。
  /// 返回经过检查和处理后的 [ResponseAnalyzed] 对象。
  static ResponseAnalyzed _resultCheck(ResponseAnalyzed result) {
    // 如果设置了结果检查回调函数，调用该回调函数处理结果。
    if (_resultCheckCallback != null) {
      _resultCheckCallback!(result);
    }
    return result;
  }
}